﻿#include "FrameBuffer.h"

FrameBuffer::FrameBuffer(int32_t width, int32_t height, bool useDepthAttachment, int32_t colorAttachmentCount)
    : m_width(width), m_height(height)
{
  glGenFramebuffers(1, &m_id);
  Bind(false);

  if (useDepthAttachment)
  {
    m_depthAttachment = CreateRef<Texture>();
    m_depthAttachment->Generate(GL_TEXTURE_2D, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT, false);
    m_depthAttachment->Allocate(width, height);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthAttachment->GetID(), 0);
  }

  for (uint32_t i = 0; i < colorAttachmentCount; i++)
  {
    Ref<Texture> attachment = CreateRef<Texture>();
    attachment->Generate(GL_TEXTURE_2D, GL_RGBA16, GL_RGBA, GL_SHORT, false, 0);
    attachment->Allocate(width, height);

    uint32_t attachmentName = GL_COLOR_ATTACHMENT0 + i;
    glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentName, GL_TEXTURE_2D, attachment->GetID(), 0);

    m_attachmentNames.push_back(attachmentName);
    m_attachments.push_back(attachment);
  }

  Unbind();
}

FrameBuffer::~FrameBuffer()
{
  m_attachments.clear();
  m_depthAttachment.reset();
  if (IsValid())
    glDeleteFramebuffers(1, &m_id);
}

void FrameBuffer::ClearColorAttachment(int32_t index, const glm::vec4 &value)
{
  Bind();
  assert(index < m_attachments.size());
  glClearBufferfv(GL_COLOR, index, &value.x);
}

void FrameBuffer::Bind(bool forDrawing) const
{
  glBindFramebuffer(GL_FRAMEBUFFER, m_id);
  if (forDrawing)
    Draw();
}

void FrameBuffer::Draw() const
{
  glDrawBuffers(static_cast<int32_t>(m_attachmentNames.size()), m_attachmentNames.data());
}

void FrameBuffer::Unbind() const
{
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
}